---
group: 'components'
category: 'state'
title: Table
description: 'Table is a component that displays data in a tabular format.'
order: 10
---

## Basic Usage

> For detailed react table usage, please refer to [react-table](https://tanstack.com/table/latest/docs/introduction)

```jsx live=true
import * as React from 'react';
import { DataTable, Table } from '@kubed/components';

() => {
  const [defaultOptions] = React.useState(
    DataTable.getDefaultTableOptions({
      tableName: 'table-demo',
      manual: false,
      enableFilters: true,
      enablePagination: false,
    })
  );
  const [columnFilters, setColumnFilters] = React.useState([]);
  const columns = React.useMemo(() => {
    return [
      {
        accessorKey: 'name',
        header: 'Name',
        cell: (info) => info.getValue(),
      },
      {
        accessorKey: 'age',
        header: 'Age',
        cell: (info) => info.getValue(),
        filterFn: 'equals',
      },
      {
        accessorKey: 'address',
        header: 'Address',
        cell: (info) => info.getValue(),
      },
    ];
  }, []);
  const data = React.useMemo(() => {
    return [
      { name: 'KubeSphere', age: 1, address: 'Beijing' },
      { name: 'KubeSphere', age: 3, address: 'Beijing' },
      { name: 'KubeSphere', age: 2, address: 'Beijing' },
    ];
  }, []);
  const table = DataTable.useTable({
    ...defaultOptions,
    columns,
    data,
    meta: {
      ...defaultOptions.meta,
      getProps: {
        filters: () => {
          return {
            simpleMode: false,
            suggestions: [
              {
                key: 'age',
                label: 'Age',
                options: Array(4)
                  .fill(1)
                  .map((i, index) => ({ key: index, label: `Age ${index}` })),
              },
            ],
          };
        },
      },
    },
  });
  return <Table table={table} />;
};
```

## useTable Extension Points

### useTable(options)

#### options.meta

Most of the extension points in the table are configured through meta.

```ts
interface TableMeta<TData extends RowData> {
  tableName: string; // table name, now only used for storage state
  refetch?: () => void; // refetch data
  storageStateKeys?: (keyof TableState)[] | '*'; // state keys need to be stored, used with Status2StorageFeature
  manual?: boolean; // whether to manually control the data
  enable?: {
    // whether to enable some features
    pagination?: boolean; // whether to enable pagination
    toolbar?: boolean; // whether to enable toolbar
    visible?: boolean; // whether to enable hidden columns
    filters?: boolean; // whether to enable filters
  };
  enableDefault?: {
    // whether to enable default functions
    toolbar?: boolean; // toolbar default functions, including multi-selection display, multi-selection operation status switching, etc.
    th?: boolean; // when th is more than one line, enable border
  };
  getProps?: {
    // custom props of each component in BaseTable, can be returned by function. Refer to BaseTable for the props of each component
    filters?: (table: Table<TData>) => BaseTable.ToolbarProps['filterProps'];
    toolbar?: (
      table: Table<TData>
    ) => Partial<Omit<BaseTable.ToolbarProps, 'filtersProps' | 'enableFilters'>>;
    table?: (table: Table<TData>) => Partial<BaseTable.TableProps>;
    th?: (
      table: Table<TData>,
      header: Header<TData, unknown>
    ) => Omit<BaseTable.TableCellProps, 'ref'>;
    pagination?: (table: Table<TData>) => Partial<BaseTable.BaseTablePaginationProps> & {
      total?: number;
    };
    tr?: (table: Table<TData>, row: Row<TData>) => Partial<BaseTable.TableRowProps>;
    td?: (table: Table<TData>, props: Record<string, any>) => Omit<BaseTable.TableCellProps, 'ref'>;
    empty?: () => Partial<BaseTable.TableFilteredEmptyProps>;
  };

  registerHandlers?: StateHandler[];
}
```

#### options.meta.registerHandlers

Extend the state processing function of the table by registering through `registerHandlers`.

When `stateKeys` is '\*', all state changes are listened to through `useEffect`. When `(keyof TableState[])`, state changes are listened to through onXXXChange.

`handleName` and `callback` are optional, and `callback` has a higher priority than `handleName`.

```ts
interface StateHandler {
  handlerName?: string; // options 中的方法名
  stateKeys: (keyof TableState)[] | '*'; // 监听的状态
  callback?: (state: Partial<TableState>) => void; // 状态变化时的回调
}
```

#### options.columns

Customize column configuration by setting `column.meta`

```ts
interface ColumnMeta<TData extends RowData, TValue = unknown> {
  description?: Record<string, any>; // icon ? tooltip props
  // filterOptions?: { key: string; label: React.ReactNode }[]; // filter options
  selectType?: 'single' | 'multiple'; // multiple selection type
  sortable?: boolean; // whether it can be sorted
  searchKey?: string; // custom search key
  th?: Partial<BaseTable.TableCellProps>; // baseTable th props, priority is higher than getProps.th
  td?: Partial<BaseTable.TableCellProps>; //baseTable td props, priority is higher than getProps.td
}
```

### Feature

#### Status2StorageFeature

After being added to \_features, the fields in the configured state are stored in localStorage by default.
getDefaultTableOptions will automatically register this feature.

- `options.state2Storage`
  The method of converting state to storage, the method of converting state to storage.
- `options.storage2State`
  The method of converting storage to state, the method of converting storage to state.
- `options.meta.storageKeys`
  Fields that need to be stored.

```ts
// storageKey field consists of kube-table-${tableName}-state
interface StorageStateOptions {
  storage2State?: (storageKey: string) => Partial<TableState>;
  state2Storage?: (storageKey: string, state: Partial<TableState>) => void;
}

interface TableMeta<TData extends RowData> {
  storageKeys?: Array<keyof TableState>;
  tableName: string;
}
```

### getDefaultTableOptions(config)

Quickly generate default options configuration

````ts
**config**:

```ts
interface Config {
  tableName: string;
  manual: boolean; // whether to manually control the data
  enableToolbar?: boolean; // whether to enable toolbar
  enablePagination?: boolean; // whether to enable pagination
  enableVisible?: boolean; // whether to enable hidden columns
  enableFilters?: boolean; // whether to enable filters
  enableStateToStorage?: boolean; // whether to store state to storage, used with options.meta.storageKeys
  enableSelection?: boolean; // whether to enable selection
  enableSort?: boolean; // whether to enable sorting
  enableMultiSelection?: boolean; // whether to enable multi-selection
  enableInitParamsByUrl?: boolean; // TODO: whether to enable url parameter initialization (not implemented)
  enableParamsToUrl?: boolean; // TODO: whether to enable url parameters (not implemented)
}
````

**Default enabled features**:

- `enableFilters`
- `enablePagination`
- `enableToolbar`
- `enableVisible`
- `enableStateToStorage`
- `enableSort`

**Default enabled Feature**:

- `Status2StorageFeature`

**Default generated configuration**:

```ts
{
  storageStateKeys: ['columnVisibility'],
  registerHandlers: manual
    ? [
        {
          handlerName: 'onParamsChange',
          stateKeys: ['pagination', 'columnFilters', 'sorting'],
        },
      ]
    : [],
}
```

## BaseTable

### BaseTable.TableProps

```ts
interface TableInnerProps {
  padding?: 'normal' | 'none';
  size?: 'small' | 'medium';
  stickyHeader?: boolean; // whether to fix the table header
  className?: string;
  style?: React.CSSProperties;
  tableWrapperClassName?: string;
}
```

### BaseTable.TableHeadProps

```ts
interface TableHeadProps {
  className?: string;
  style?: React.CSSProperties;
  hasBorder?: boolean; // whether the table th has a border
}
```

### BaseTable.TableBodyProps

```ts
interface TableBodyProps {
  className?: string;
  style?: React.CSSProperties;
  hasBorder?: boolean; // whether the td in the table body has a border
}
```

### BaseTable.TableRowProps

```ts
export interface TableRowProps {
  className?: string;
  hover?: boolean; // whether hover effect
  selected?: boolean; // whether selected
  style?: React.CSSProperties;
}
```

### BaseTable.TableCellProps

```ts
/**
when padding is normal, variant and size correspond to the padding attributeQ
  'head-small': '8px 12px',
  'head-medium': '16px 12px',
  'body-small': '4px 8px',
  'body-medium': '8px 12px',
*/
export type TableCellProps = {
  padding?: 'none' | 'normal'; // cell padding
  align?: 'left' | 'center' | 'right' | 'justify'; // cell alignment
  className?: string;
  size?: 'small' | 'medium'; // cell size
  ariaSort?: 'asc' | 'desc' | false; // whether to sort
  variant?: 'head' | 'body'; // distinguish th and td
  stickyHeader?: boolean; // whether to fix the table header
  fixed?: 'left' | 'right'; // fixed column
  fixedWidth?: number; // width when the column is fixed (when position is sticky; left or right value)
  fixedLastLeft?: boolean; // whether it is the most left fixed, mainly used to separate shadow effects
  fixedLastRight?: boolean; // whether it is the most right fixed, mainly used to separate shadow effects
  style?: React.CSSProperties;
  hasBorder?: boolean;
};
```

### BaseTable.ToolbarProps

```ts
interface ToolbarProps {
  enableBatchActions: boolean; //  Whether to operate when multiple selections
  enableSettingMenu?: boolean; //  Whether to temporarily operate the button
  onDisableBatchActions?: () => void; //  Cancel the multi-selection operation box
  enableFilters?: boolean; //  Whether to enable filtering
  settingMenu?: React.ReactNode; //  Operation list
  settingMenuText?: string;
  toolbarLeft?: React.ReactNode; //  left component
  toolbarRight?: React.ReactNode; //  right component
  batchActions?: React.ReactNode; //  Multi-selection operation button
  filterProps: {
    // FilterInput props
    filters?: any;
    placeholder?: string;
    suggestions: Suggestions;
    simpleMode?: boolean;
    onChange?: (value: any) => void;
    initialKeyword?: string;
  };
  onFilterInputChange?: (value: any) => void; // FilterInput onChange
  refetch?: any; //  refresh
  loading?: boolean; //  loading on the refresh button
}
```

### BaseTable.EmptyProps

```ts
//  empty create button props
interface CreateButtonProps {
  enableCreate?: boolean;
  createButton?: ReactElement;
  clickCreateButtonFn?: (event: MouseEvent<HTMLButtonElement>) => void;
}

//  data is empty, no filter conditions
export type TableEmptyProps = PropsWithChildren<EmptyProps & CreateButtonProps>;

interface DescriptionProps {
  clearAndRefetch?: false | (() => void); //  clear filter conditions
  refetch?: false | (() => void); //  refresh
}

//  data is empty, with filter conditions
export type TableFilteredEmptyProps = TableEmptyProps & DescriptionProps;
```

## Full example

```js live=true
import { Table, DataTable, Dropdown, Menu } from '@kubed/components;';

export const App = () => {
  const defaultColumns = React.useMemo(
    () => [
      {
        header: 'Name',
        footer: (props) => props.column.id,
        columns: [
          {
            accessorFn: (row) => {
              return row.firstName;
            },
            accessorKey: 'firstName',
            cell: (info) => info.getValue(),
            footer: (props) => props.column.id,
          },
          {
            accessorFn: (row) => row.lastName,
            id: 'lastName',
            cell: (info) => info.getValue(),
            header: () => <span>Last Name</span>,
            footer: (props) => props.column.id,
            enableHiding: true,
          },
        ],
      },
      {
        header: 'Info',
        footer: (props) => props.column.id,
        columns: [
          {
            accessorKey: 'age',
            header: () => 'Age',
            footer: (props) => props.column.id,
            meta: {
              sortable: true,
            },
          },
          {
            header: 'More Info',
            columns: [
              {
                accessorKey: 'visits',
                header: () => <span>Visits</span>,
                footer: (props) => props.column.id,
              },
              {
                accessorKey: 'status',
                header: 'Status',
                footer: (props) => props.column.id,
                meta: {
                  searchKey: 'status1',
                },
              },
              {
                accessorKey: 'progress',
                header: 'Profile Progress',
                footer: (props) => props.column.id,
              },
            ],
          },
        ],
      },
      {
        id: 'actions',
        cell: () => (
          <Dropdown
            content={
              <Menu>
                <MenuItem>Edit</MenuItem>
              </Menu>
            }
          >
            <Button variant="text" radius="lg">
              More
            </Button>
          </Dropdown>
        ),
      },
    ],
    []
  );

  const [params, setParams] = React.useState({
    pagination: {
      pageIndex: 0,
      pageSize: 10,
    },
    columnFilters: [],
    sorting: [],
  });
  const { pagination = {} } = params;
  const [rowSelection, setRowSelection] = React.useState({}); //manage your own row selection state

  const handleParams = (p, key) => {
    setRowSelection({});
    const { pagination: page } = p;
    if (key === 'pagination') {
      setParams(p);
    } else {
      setParams({
        ...p,
        pagination: {
          ...page,
          pageIndex: 0,
        },
      });
    }
  };
  const [loading, setLoading] = React.useState(true);
  React.useEffect(() => {
    setLoading(true);
    setTimeout(() => {
      setLoading(false);
    }, 2000);
  }, [params]);
  const [columns] = React.useState(() => [
    {
      id: 'selection',
      header: ({ table }) => (
        <Checkbox
          checked={table.getIsAllRowsSelected()}
          indeterminate={table.getIsSomeRowsSelected()}
          onChange={table.getToggleAllRowsSelectedHandler()} //or getToggleAllPageRowsSelectedHandler
        />
      ),
      cell: ({ row }) => (
        <Checkbox
          checked={row.getIsSelected()}
          disabled={!row.getCanSelect()}
          onChange={row.getToggleSelectedHandler()}
        />
      ),
    },
    ...defaultColumns,
  ]);
  const total = 100;
  const data = React.useMemo(() => {
    if (loading) {
      return [];
    }
    return Array.from({ length: pagination.pageSize })
      .fill(1)
      .map((_, i) => {
        return {
          firstName: `page-${pagination.pageIndex}-firstName-${i}`,
          lastName: `lastName-${i}`,
          age: i,
          visits: i,
          status: `status-${i}`,
          progress: i,
        };
      });
  }, [params, loading]);

  const state = React.useMemo(() => {
    return {
      ...params,
      rowSelection,
    };
  }, [params, rowSelection]);

  const forceUpdate = React.useReducer(() => ({}), {})[1];

  const defaultOption = React.useState(
    DataTable.getDefaultTableOptions({
      tableName: 'table1',
      manual: true,
      enableSelection: true,
      enableMultiSelection: true,
    })
  )[0];

  const table = DataTable.useTable({
    ...defaultOption,
    data,
    loading,
    columns,
    onRowSelectionChange: setRowSelection,
    onParamsChange: handleParams,
    rowCount: total,
    //  getRowId: (row) => row.firstName,
    state,
    meta: {
      ...defaultOption.meta,
      tableName: defaultOption.meta.tableName,
      getProps: {
        filters: () => {
          return {
            simpleMode: false,
            suggestions: [
              {
                key: 'age',
                label: 'Age',
                options: [
                  {
                    key: '0',
                    label: '0',
                  },
                  {
                    key: '1',
                    label: '1',
                  },
                ],
              },
              {
                key: 'status1',
                label: 'Status',
                options: [
                  {
                    key: 'status-0',
                    label: 'status-0',
                  },
                  {
                    key: 'status-1',
                    label: 'status-1',
                  },
                ],
              },
            ],
          };
        },
      },
    },
  });

  return (
    <>
      <Table table={table} />
      <pre>{JSON.stringify(state, null, 2)}</pre>
    </>
  );
};
```

### Base Table

BaseTable is a basic table component that provides some fundamental table components, such as Table, TableHead, TableBody, TableRow, TableCell.

```jsx live=true
import { BaseTable } from '@kubed/components';
() => {
  const { Table, TableHead, TableBody, TableRow, TableCell } = BaseTable;
  return (
    <>
      <Table>
        <TableHead>
          <TableRow>
            <TableCell>Header 1</TableCell>
            <TableCell>Header 2</TableCell>
            <TableCell>Header 3</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          <TableRow>
            <TableCell>Cell 1</TableCell>
            <TableCell>Cell 2</TableCell>
            <TableCell>Cell 3</TableCell>
          </TableRow>
          <TableRow>
            <TableCell>Cell 4</TableCell>
            <TableCell>Cell 5</TableCell>
            <TableCell>Cell 6</TableCell>
          </TableRow>
        </TableBody>
      </Table>
    </>
  );
};
```

### baseTable selected

```jsx live=true
import { BaseTable } from '@kubed/components';

() => {
  const { Table, TableHead, TableBody, TableRow, TableCell } = BaseTable;
  const [selectIds, setSelectIds] = React.useState([]);
  const handleSelect = (id) => {
    setSelectIds((ids) => {
      if (ids.includes(id)) {
        return ids.filter((i) => i !== id);
      }
      return [...ids, id];
    });
  };
  return (
    <>
      <Table>
        <TableHead>
          <TableRow>
            <TableCell>
              <Checkbox
                checked={selectIds.length > 0 && selectIds.length === 2}
                indeterminate={selectIds.length > 0 && selectIds.length < 2}
                onChange={() => {
                  if (selectIds.length > 0) {
                    setSelectIds([]);
                  } else {
                    setSelectIds(['1', '2']);
                  }
                }}
              />
            </TableCell>
            <TableCell>Header 1</TableCell>
            <TableCell>Header 2</TableCell>
            <TableCell>Header 3</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          <TableRow selected={selectIds.includes('1')}>
            <TableCell>
              <Checkbox checked={selectIds.includes('1')} onChange={() => handleSelect('1')} />
            </TableCell>
            <TableCell>Cell 1</TableCell>
            <TableCell>Cell 2</TableCell>
            <TableCell>Cell 3</TableCell>
          </TableRow>
          <TableRow selected={selectIds.includes('2')}>
            <TableCell>
              <Checkbox checked={selectIds.includes('2')} onChange={() => handleSelect('2')} />
            </TableCell>
            <TableCell>Cell 4</TableCell>
            <TableCell>Cell 5</TableCell>
            <TableCell>Cell 6</TableCell>
          </TableRow>
        </TableBody>
      </Table>
    </>
  );
};
```

### BaseTable Header Fixed

```jsx live=true
import { BaseTable } from '@kubed/components';
import * as React from 'react';

() => {
  const { Table, TableHead, TableBody, TableRow, TableCell } = BaseTable;
  const data = React.useMemo(() => {
    return [...Array(100)].fill(1).map((_, i) => ({
      col1: i,
      col2: `col2-${i}`,
      col3: `col3-${i}`,
    }));
  }, []);
  return (
    <div
      style={{
        height: '300px',
        overflowY: 'auto',
      }}
    >
      <Table stickyHeader>
        <TableHead hasBorder>
          <TableRow>
            <TableCell colSpan={2}>Header 1</TableCell>
            <TableCell colSpan={1}>Header 2</TableCell>
          </TableRow>
          <TableRow>
            <TableCell>Header 1</TableCell>
            <TableCell>Header 2</TableCell>
            <TableCell>Header 3</TableCell>
          </TableRow>
        </TableHead>
        <TableBody hasBorder>
          {data.map((row) => (
            <TableRow key={row.col1}>
              <TableCell>{row.col1}</TableCell>
              <TableCell>{row.col2}</TableCell>
              <TableCell>{row.col3}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </div>
  );
};
```

### BaseTable Column Fixed

```jsx live=true
import { BaseTable } from '@kubed/components';
import * as React from 'react';

() => {
  const { Table, TableHead, TableBody, TableRow, TableCell } = BaseTable;
  const data = React.useMemo(() => {
    return [...Array(100)].fill(1).map((_, i) => ({
      col1: i,
      col2: `col2-${i}`,
      col3: `col3-${i}`,
    }));
  }, []);
  return (
    <div
      style={{
        height: '300px',
        overflow: 'auto',
        width: 500,
      }}
    >
      <Table
        stickyHeader
        style={{
          width: 700,
          minWidth: '100%',
        }}
      >
        <colgroup>
          <col width="100" />
          <col width="200" />
          <col />
          <col />
          <col />
          <col width="100" />
        </colgroup>
        <TableHead hasBorder>
          <TableRow>
            <TableCell fixed="left" fixedWidth={0} width={100}>
              Header 1
            </TableCell>
            <TableCell fixed="left" fixedWidth={100} fixedLastLeft>
              Header 2
            </TableCell>
            <TableCell>Header 3</TableCell>
            <TableCell>Header 3</TableCell>
            <TableCell>Header 3</TableCell>
            <TableCell fixed="right" fixedLastRight fixedWidth={0}>
              Header 3
            </TableCell>
          </TableRow>
        </TableHead>
        <TableBody hasBorder>
          {data.map((row) => (
            <TableRow key={row.col1}>
              <TableCell fixed="left" fixedWidth={0}>
                {row.col1}
              </TableCell>
              <TableCell fixed="left" fixedWidth={100} fixedLastLeft>
                <div> {row.col2}</div>
              </TableCell>
              <TableCell>
                <div>{row.col3}</div>
              </TableCell>
              <TableCell>{row.col3}</TableCell>
              <TableCell>{row.col3}</TableCell>
              <TableCell fixed="right" fixedLastRight fixedWidth={0}>
                {row.col3}
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </div>
  );
};
```

### BaseTable Pagination

```jsx live=true
import { BaseTable } from '@kubed/components';
import * as React from 'react';

() => {
  const [state, setState] = React.useState({});
  return <BaseTable.Pagination total={100} pagination={state} onChange={setState} />;
};
```

### BaseTable with toolbar

```jsx live=true
import { BaseTable } from '@kubed/components';
import * as React from 'react';

() => {
  const { Table, TableHead, TableBody, TableRow, TableCell, Toolbar, Pagination } = BaseTable;
  const [page, setPage] = React.useState(1);
  const [pageSize, setPageSize] = React.useState(10);
  const [selectedIds, setSelectedIds] = React.useState([]);

  const handlePaginationChange = (pagination) => {
    setPage(pagination.page);
    setPageSize(pagination.pageSize);
    setSelectedIds([]);
  };

  const data = React.useMemo(() => {
    return [...Array(10)].fill(1).map((_, i) => ({
      col1: `page-${page}-col1-${i}`,
      col2: `page-${page}-col2-${i}`,
      col3: `page-${page}-col3-${i}`,
    }));
  }, [page]);

  const handleSelect = (id) => {
    setSelectedIds((ids) => {
      if (ids.includes(id)) {
        return ids.filter((i) => i !== id);
      }
      return [...ids, id];
    });
  };

  const enableBatchActions = selectedIds.length > 0;
  const setEnableBatchActions = () => {
    setSelectedIds([]);
  };

  return (
    <>
      <Toolbar
        enableBatchActions={enableBatchActions}
        onDisableBatchActions={setEnableBatchActions}
        enableFilters={false}
        filterProps={{
          suggestions: [],
          onChange: () => {},
        }}
        toolbarRight={<div>Toolbar Right</div>}
      />
      <Table
        stickyHeader
        style={{
          width: 700,
          minWidth: '100%',
        }}
      >
        <colgroup>
          <col width="100" />
          <col width="100" />
          <col width="100" />
          <col />
          <col width="100" />
          <col width="100" />
        </colgroup>
        <TableHead>
          <TableRow>
            <TableCell fixed="left" fixedWidth={0}>
              <Checkbox
                checked={selectedIds.length > 0 && selectedIds.length === 2}
                indeterminate={selectedIds.length > 0 && selectedIds.length < 2}
                onChange={() => {
                  if (selectedIds.length > 0) {
                    setSelectedIds([]);
                  } else {
                    setSelectedIds(['1', '2']);
                  }
                }}
              />
            </TableCell>
            <TableCell fixed="left" fixedWidth={100} fixedLastLeft>
              Header 2
            </TableCell>
            <TableCell>Header 3</TableCell>
            <TableCell>Header 3</TableCell>
            <TableCell>Header 3</TableCell>
            <TableCell>Header 3</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {data.map((row) => (
            <TableRow key={row.col1} selected={selectedIds.includes(row.col1)}>
              <TableCell fixed="left" fixedWidth={0}>
                <Checkbox
                  checked={selectedIds.includes(row.col1)}
                  onChange={() => handleSelect(row.col1)}
                />
              </TableCell>
              <TableCell fixed="left" fixedWidth={100} fixedLastLeft>
                <div> {row.col2}</div>
              </TableCell>
              <TableCell>
                <div>{row.col3}</div>
              </TableCell>
              <TableCell>{row.col3}</TableCell>
              <TableCell>{row.col3}</TableCell>
              <TableCell>{row.col3}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
      <Pagination
        total={100}
        pagination={{
          page,
          pageSize,
        }}
        onChange={handlePaginationChange}
      />
    </>
  );
};
```
